package com.tanger.pay.wechat;

import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Description 微信支付、退款、提现到零钱
 * @Author Hchenbin
 * @Date 2024-01-04 17:19
 * @Version 1.0
 */
@Slf4j
public class WeChatPayHelper {

    /**
     * @Description 扫码支付, 返回付款url地址
     */
    public static String qrCodePay(WeChatPay weChatPay) {
        //预订单参数生成
        Map params = new HashMap<String, String>();
        params.put("appid", weChatPay.getAppId());
        params.put("mch_id", weChatPay.getMchId());
        params.put("body", weChatPay.getBody());
        params.put("trade_type", weChatPay.getTradeType());
        params.put("nonce_str", weChatPay.getNonceStr());
        params.put("notify_url", weChatPay.getNotifyUrl());
        params.put("out_trade_no", weChatPay.getOutTradeNo());
        params.put("total_fee", weChatPay.getTotalFee());
        params.put("spbill_create_ip", weChatPay.getSpbillCreateIp());
        params.put("product_id", weChatPay.getProductId());
        params.put("sign", WeChatUtil.sign(params));
        //转成xml
        String reqXml = MapXmlUtil.map2Xml(params);
        //发送请求
        String respStr = HttpUtil.sendPost(WeChatPayConfig.unifiedorderUrl, reqXml);
        //转成map
        Map respParams = MapXmlUtil.xml2Map(respStr);
        //获取到可生成二维码的url链接
        if ("SUCCESS".equals(respParams.get("return_code"))) {
            if (respParams.get("code_url") == null) {
                return null;
            }
            return respParams.get("code_url").toString();
        }
        return null;
    }

    /**
     * @Description: app支付, 返回app调起支付所需值, map返回
     */
    public static Map<String, String> appPay(WeChatPay weChatPay) {
        //预订单参数生成
        Map params = new HashMap<String, String>();
        params.put("appid", weChatPay.getAppId());
        params.put("mch_id", weChatPay.getMchId());
        params.put("body", weChatPay.getBody());
        params.put("trade_type", weChatPay.getTradeType());
        params.put("nonce_str", weChatPay.getNonceStr());
        params.put("notify_url", weChatPay.getNotifyUrl());
        params.put("out_trade_no", weChatPay.getOutTradeNo());
        params.put("total_fee", weChatPay.getTotalFee());
        params.put("spbill_create_ip", weChatPay.getSpbillCreateIp());
        params.put("sign", WeChatUtil.sign(params));
        //转成xml
        String reqXml = MapXmlUtil.map2Xml(params);
        //发送请求
        String respStr = HttpUtil.sendPost(WeChatPayConfig.unifiedorderUrl, reqXml);
        //转成map
        Map respParams = MapXmlUtil.xml2Map(respStr);
        //获取prepayId
        if ("SUCCESS".equals(respParams.get("return_code"))) {
            if (respParams.get("prepayId") == null) {
                return null;
            }
            String prepayId = respParams.get("prepayId").toString();
            Map map = new HashMap<String, String>();
            map.put("appid", params.get("appid"));
            map.put("partnerid", params.get("mch_id"));
            map.put("prepayid", prepayId);
            map.put("package", "Sign=WXPay");
            map.put("noncestr", UUID.randomUUID().toString().replaceAll("-", ""));
            map.put("timestamp", System.currentTimeMillis() / 1000);
            map.put("sign", params.get("sign"));
            return map;
        }
        return null;
    }

    /**
     * @Description: 小程序支付, 返回小程序调起支付所需值, map返回
     */
    public static Map<String, String> xcxPay(WeChatPay weChatPay) {
        //预订单参数生成
        Map params = new HashMap<String, String>();
        params.put("appid", weChatPay.getAppId());
        params.put("mch_id", weChatPay.getMchId());
        params.put("body", weChatPay.getBody());
        params.put("trade_type", weChatPay.getTradeType());
        params.put("nonce_str", weChatPay.getNonceStr());
        params.put("notify_url", weChatPay.getNotifyUrl());
        params.put("out_trade_no", weChatPay.getOutTradeNo());
        params.put("total_fee", weChatPay.getTotalFee());
        params.put("spbill_create_ip", weChatPay.getSpbillCreateIp());
        params.put("openid", weChatPay.getOpenId());
        params.put("sign", WeChatUtil.sign(params));
        //转成xml
        String reqXml = MapXmlUtil.map2Xml(params);
        //发送请求
        String respStr = HttpUtil.sendPost(WeChatPayConfig.unifiedorderUrl, reqXml);
        //转成map
        Map respParams = MapXmlUtil.xml2Map(respStr);
        //获取prepayId
        if ("SUCCESS".equals(respParams.get("return_code"))) {
            if (respParams.get("prepayId") == null) {
                return null;
            }
            String prepayId = respParams.get("prepayId").toString();
            Map map = new HashMap<String, String>();
            map.put("appid", params.get("appid"));
            map.put("timestamp", System.currentTimeMillis() / 1000);
            map.put("noncestr", UUID.randomUUID().toString().replaceAll("-", ""));
            map.put("package", "prepay_id=" + prepayId);
            map.put("signType", "MD5");
            return map;
        }
        return null;
    }

    /**
     * @Description 微信退款
     */
    public static Map<String, String> refund(WeChatRefund weChatRefund) {
        try {
            Map params = new HashMap<String, String>();
            params.put("appid", weChatRefund.getAppId());
            params.put("mch_id", weChatRefund.getMchId());
            params.put("nonce_str", weChatRefund.getNonceStr());
            params.put("out_trade_no", weChatRefund.getOutTradeNo());
            params.put("notify_url", weChatRefund.getNotifyUrl());
            params.put("out_refund_no", weChatRefund.getOutRefundNo());
            params.put("total_fee", weChatRefund.getTotalFee());
            params.put("refund_fee", weChatRefund.getRefundFee());
            params.put("sign", WeChatUtil.sign(params));
            //转成xml
            String reqXml = MapXmlUtil.map2Xml(params);
            //发送请求
            String respStr = HttpUtil.sendPost(WeChatPayConfig.refundUrl, reqXml);
            //返回map
            return MapXmlUtil.xml2Map(respStr);
//        //获取到可生成二维码的url链接
//        if ("SUCCESS".equals(respParams.get("return_code"))) {
//            //执行业务处理
//        }
        } catch (Exception e) {
            log.error("Refund failed! reason: {}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * @Description 微信提现
     */
    public static Map<String, String> withdrawal(String money, String openId) {
        try {
            SortedMap<String, String> paramMap = new TreeMap<>();
            paramMap.put("mch_appid", WeChatPayConfig.appId);
            paramMap.put("mchid", WeChatPayConfig.mchId);
            paramMap.put("nonce_str",WeChatUtil.randomStr());

            //提现的订单，恶意刷的可以找回
            String orderNo = "C" + System.currentTimeMillis();
            paramMap.put("partner_trade_no", orderNo);
            paramMap.put("openid", openId);
            // 校验方式
            paramMap.put("check_name", "NO_CHECK");

            /**
             * 这里我 就遇到了很多坑，经常报错 金额的可是不对，
             * 有时候你的程序提现需要手续费，这时候你的金额是需要用double来计算的
             * 下面的代码是你计算完取证方法
             * BigDecimal total = new BigDecimal(money).multiply(new BigDecimal(100))
             *        .setScale(0);
             * 比如 你提100，程序手续费3%  100-100*3%=97.00  注意因为double就算是整数后面还是有小数
             * 这样你这里给微信提现的时候就会多后面的 .00 用上去整就可以就解决掉
             */
            //转换 类型   这里可以去百度下，如果这样写会报错 金额的格式错误
            BigDecimal total = new BigDecimal(money).multiply(new BigDecimal(100));
            paramMap.put("amount", total.toString());

            paramMap.put("desc", "提现");
//            //IP
//            paramMap.put("spbill_create_ip", WeChatUtil.getLocalIp());
            //这里就是在上个代码里面的回调地址  没啥用
//          paramMap.put("spbill_create_ip", "http://localhost:10118/tanger/bts/pay/notify");
            String sign = WeChatUtil.sign(paramMap);
            paramMap.put("sign", sign);
            //构造提现配置
            WXPayConfig config = new WXPayFactory();
            WXPay pay = new WXPay(config);
            String xmlStr = pay.requestWithCert(WeChatPayConfig.transfers, paramMap, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());

            //调用解析xml工具 返回解析结果
            return MapXmlUtil.xml2Map(xmlStr);
//            //判断 返回的里面有没有SUCCESS 代表成功
//            if ("SUCCESS".equalsIgnoreCase(resMap.get("result_code"))) {
//                //走到这里就是提现操作成功了，可以做你自己的业务逻辑了、
//            }
        } catch (Exception e) {
            log.error("Refund failed! reason: {}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }
}
